package ch.fhnw.qualiscan.application.pages;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;

import ch.fhnw.qualiscan.AppObject;
import ch.fhnw.qualiscan.Config;
import ch.fhnw.qualiscan.application.elements.AnswersLegendBox;
import ch.fhnw.qualiscan.application.elements.EvaluationDomain;
import ch.fhnw.qualiscan.application.elements.EvaluationOptionsBox;
import ch.fhnw.qualiscan.application.models.DomainModel;
import ch.fhnw.qualiscan.application.models.RoleModel;
import ch.fhnw.qualiscan.application.models.SurveyModel;
import ch.fhnw.qualiscan.application.models.UserModel;
import ch.fhnw.qualiscan.core.Page;
import ch.fhnw.qualiscan.core.db.pojos.Domain;
import ch.fhnw.qualiscan.core.db.pojos.Role;
import ch.fhnw.qualiscan.core.db.pojos.RoleText;
import ch.fhnw.qualiscan.core.db.pojos.Survey;
import ch.fhnw.qualiscan.core.db.pojos.SurveyUserRole;
import ch.fhnw.qualiscan.core.db.pojos.User;
import ch.fhnw.qualiscan.core.helpers.Filter;
import ch.fhnw.qualiscan.core.libraries.NotificationLib;

import com.vaadin.data.Property;
import com.vaadin.data.Property.ValueChangeEvent;
import com.vaadin.ui.HorizontalLayout;
import com.vaadin.ui.Label;
import com.vaadin.ui.OptionGroup;
import com.vaadin.ui.VerticalLayout;

import eu.livotov.tpt.TPTApplication;
import eu.livotov.tpt.i18n.TM;

@SuppressWarnings("serial")
public class Evaluation extends Page  {
	
	// design variables
	HorizontalLayout wrapper;
	VerticalLayout content;
	HorizontalLayout rolePicker;
	VerticalLayout charts;
	
	Label title;
	OptionGroup rolesSelect = null;
	Label rolesSelectCaption;
	
	User user;
	// models
	RoleModel roleModel;
	SurveyModel surveyModel;
	DomainModel domainModel;
	UserModel userModel;
	
	// runtime vars
	int currentFilter;
	Filter filter;
	ArrayList<EvaluationDomain> allDomains = new ArrayList<EvaluationDomain>();
	
	// other 
	AppObject appObject; 
	
	// determined by parameters
	public Survey currentSurvey;
	public SurveyUserRole sur;
	int currentRole;
	
	@Override
	public void initModelsAndHelpers() {
		user = new User();
		user.setId(userSession.getId());
		
		roleModel = new RoleModel();
		surveyModel = new SurveyModel();
		domainModel = new DomainModel();
		userModel = new UserModel();
		
		filter = new Filter();
		
		// standard filter
		filter.setRoleId(0);
	}
	
	@Override
	public void buildLayout() {
		
		// build wrapper
		wrapper = new HorizontalLayout();
		wrapper.setWidth("100%");
		wrapper.setSpacing(true);
		
		content = new VerticalLayout();
		content.setSpacing(true);
		content.setWidth("100%");
		
		charts = new VerticalLayout();
		charts.setSpacing(true);

		wrapper.addComponent(content);
		
		addComponent(wrapper);
	}
	
	/**
	 * Builds the role picker widget in the top
	 * @return layout component
	 */
	public HorizontalLayout rolePicker() {
		rolePicker = new HorizontalLayout();
		rolePicker.setSpacing(true);
		rolePicker.setStyleName("rolePicker");
		rolePicker.setMargin(true);
		rolePicker.setCaption(TM.get("evaluation.filter"));
		
		rolesSelectCaption = textHelper.span(TM.get("evaluation.rolepicker.caption"));
		rolesSelectCaption.setWidth("100px");
		
		VerticalLayout roleList = new VerticalLayout();
		roleList.setSpacing(true);
		
		ArrayList<Role> roles = roleModel.getRoles(currentSurvey);
		ArrayList<RoleText> roleTexts = new ArrayList<RoleText>();
		for (int r = 0; r  < roles.size(); r++) {
			roleTexts.add(userModel.getRoleText(roles.get(r), userSession.getLanguage()));
		}
		roleTexts.size();
		
		// build index
		List<Integer> answers = new ArrayList<Integer>();
		answers.add(0);
		for(RoleText o : roleTexts) {
			answers.add(o.getRole().getId());
		}

		rolesSelect = new OptionGroup(null, answers);
		rolesSelect.setWidth("190px");
		rolesSelect.setItemCaption(0, TM.get("evaluation.rolepicker.all"));
		for (RoleText o : roleTexts) {
			rolesSelect.setItemCaption(o.getRole().getId(), o.getTitle());
		}
		rolesSelect.select(0);
		
		rolesSelect.setImmediate(true);
		rolesSelect.addListener(new Property.ValueChangeListener() {
			public void valueChange(ValueChangeEvent event) {
				Integer roleId = Integer.parseInt(event.getProperty().getValue().toString());
				changeFilter(roleId);
			}
		});
		
		rolePicker.addComponent(rolesSelectCaption);
		rolePicker.addComponent(rolesSelect);
	
		return rolePicker;
	}
	
	/**
	 * This function changes the filter parameter in the url.
	 */
	public void changeFilter(int roleId) {
		appObject = (AppObject) TPTApplication.getCurrentApplication().getMainWindow().getData();
		appObject.getUrlLib().setTab(roleId);
		
		/* update color
		rolePicker.removeStyleName(""+currentFilter);
		currentFilter = roleId;
		rolePicker.setStyleName("color_" + roleId);*/
		
		// update checkbox
		if(rolesSelect != null)
			rolesSelect.select((Object) currentRole);
	}
	
	
	@Override
	public void setNeededPermissions() {
		neededPermissions.add("loggedIn");
	}

	@Override
	public void initComponents() {
		
	}
	
	@Override
	public void secondParameterChanged(int secondParameter) {
		
		Role roleCheck = roleModel.getRoleById(secondParameter);
		if(roleCheck != null) {
			currentRole = roleCheck.getId();
			changeFilter(currentRole);
			filter.setRoleId(currentRole);
			update(filter);
		} else if(secondParameter == 0) {
			currentRole = 0;
			changeFilter(currentRole);
			filter.setRoleId(currentRole);
			update(filter);
		}
		else {
			currentRole = -1;
			unload();
			NotificationLib.showError(TM.get("error"), TM.get("evaluation.error.second.parameter"));
		}
	}
	
	@Override
	public void thirdParameterChanged(String currentUrl) {
		try {
			int surId = Integer.parseInt(currentUrl);
			
			sur = surveyModel.getSurById(surId);
			currentSurvey = sur.getSurvey();
			filter.setSurveyId(currentSurvey.getId());
			filter.setSurId(surId);
			// check if survey exists and whether user has access
			if (sur.getUser().getId() != user.getId()) {
				urlLib.setPage("PermissionDenied");
			}
				
			if(currentSurvey != null /*&& thisSurvey.getStage().getId() == Config.STAGE_EVALUATION*/) {
				populatePage();
				loadContent();
			} else {
				unload();
				NotificationLib.showError(TM.get("error"), TM.get("evaluation.error.access"));
			}
			
		} catch(NumberFormatException e) {
			NotificationLib.showError(TM.get("error"), TM.get("error.parameter.invalid"));
		}
		
	}
	
	/**
	 * Loads the static part once.
	 */
	public void populatePage() {
		content.removeAllComponents();
		
		title = textHelper.h1(TM.get("evaluation.title", currentSurvey.getTitle()));
		Label subTitle = textHelper.h2(TM.get("evaluation.domains"));
		
		// design workarounds
		HorizontalLayout spacer1 = new HorizontalLayout();
		spacer1.setHeight("35px");
		
		HorizontalLayout spacer2 = new HorizontalLayout();
		spacer2.setHeight("15px");
		
		// title
		content.addComponent(title);
		if(currentSurvey.getStage().getId() == Config.STAGE_SURVEY) {
			HorizontalLayout warningWrap = new HorizontalLayout();
			warningWrap.setMargin(true);
			warningWrap.setSpacing(true);
			Label surveyOpen = textHelper.p(TM.get("warning.surveyopen"));
			warningWrap.addComponent(surveyOpen);
			warningWrap.setStyleName("box-warning");
			content.addComponent(warningWrap);
		}
		content.addComponent(spacer2);
		
		// header
		HorizontalLayout header = new HorizontalLayout();
		HorizontalLayout rolePicker = rolePicker();
		VerticalLayout legend = new AnswersLegendBox();
		VerticalLayout options = new EvaluationOptionsBox(sur);
		
		header.addComponent(rolePicker);
		header.addComponent(options);
		header.addComponent(legend);
		
		content.addComponent(header);
		
		// charts
		content.addComponent(spacer1);
		
		content.addComponent(charts);
	}
	
	/**
	 * This function is responsible for loading the content
	 * @return status
	 */
	public boolean loadContent() {
		// load content (role and survey determined)
		if(currentRole >= 0 && currentSurvey != null) {
			
			charts.removeAllComponents();
			
			// loading domains
			Set<Domain> domains = currentSurvey.getDomains();
			
			for(Domain d : domains) {
				EvaluationDomain domainElement = new EvaluationDomain(this, d, filter);
				charts.addComponent(domainElement);
				allDomains.add(domainElement);
			}
			
			return true;
		} 
		
		// not enough data to load content
		else {
			return false;
		}
	}
	
	public void update(Filter filter) {
		for(EvaluationDomain d : allDomains) {
			d.update(filter);
		}
	}
	
	/**
	 * this function unloads the charts
	 */
	public void unload() {
		charts.removeAllComponents();
	}
	
}
